package com.yeyks.exception;

import com.auth0.jwt.exceptions.JWTDecodeException;
import com.yeyks.common.appcommon.result.CommonResult;
import com.yeyks.common.exception.OftenFiledException;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.exception.TokenInvalidException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.ServletException;
import javax.validation.UnexpectedTypeException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * admin app 全局统一异常处理
 * @author Administrator
 */
@RestControllerAdvice
@Slf4j
public class AdminAppExceptionHandler {


    @ExceptionHandler(TokenInvalidException.class)
    public CommonResult handTokenInvalidException(TokenInvalidException ex){

        log.error("异常信息ex:" + ex);
        return CommonResult.tokenEnable("token失效");
    }

    @ExceptionHandler(JWTDecodeException.class)
    public CommonResult handJWTDecodeException(JWTDecodeException ex){

        log.error("异常信息ex:" + ex);
        return CommonResult.failed("JWT抛出的异常信息");
    }

    /**
     * 对象中属性message
     * @param ex bindException
     * @return 返回结果
     */
    @ExceptionHandler(BindException.class)
    public CommonResult handleBindException(BindException ex) {
        List<FieldError> errors = ex.getBindingResult().getFieldErrors();

        Map<String, String> errorMap = errors.stream().collect(
                Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage,(entity1, entity2) -> entity1)
        );

        log.warn("BindException,内容", ex);

        return CommonResult.create(errorMap,CommonResult.FAILED, this.getErrorMsg(errorMap));
    }

    @ExceptionHandler(ServiceException.class)
    public CommonResult handleServiceException(ServiceException ex){

        log.warn("ServiceException,内容", ex);

        return CommonResult.create(null, CommonResult.NO_PERMISSION,"没有权限访问,权限异常");
    }

    @ExceptionHandler(OftenFiledException.class)
    public CommonResult handleOftenFiledException(OftenFiledException often){

        log.warn("常见的一些异常信息,内容", often);
        if(often.getCode() != 0){
            return CommonResult.create(null, often.getCode() ,often.getMessage());
        }
        return CommonResult.create(null, CommonResult.FAILED,often.getMessage());
    }

    /**
     * 从异常的map中得到异常信息
     *
     * @param errorMap 错误信息集合
     * @return 返回消息结果
     */
    private String getErrorMsg(Map<String, String> errorMap) {
        String msg = "参数验证失败";
        if (errorMap != null) {
            Iterator iter = errorMap.entrySet().iterator();
            Map.Entry entry = (Map.Entry) iter.next();
            if (entry != null) {
                String entryValue = entry.getValue().toString();
                if (entryValue != null && entryValue.trim().length() > 0) {
                    msg = entryValue;
                }
            }
        }
        return msg;
    }


    @ExceptionHandler(DuplicateKeyException.class)
    public CommonResult handleDuplicateKeyException(DuplicateKeyException e){

        log.error(e.getMessage(), e);
        return CommonResult.create(e, CommonResult.DATA_IS_EXIST, "数据库中已存在该记录");
    }

    /**
     * 入参的校验，如果没有这个必须字段，进入校验
     * @param e 异常
     * @return 返回结果
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public CommonResult handleMissingServletRequestParameterException(MissingServletRequestParameterException e){

        //参数错误
        log.error(e.getMessage(), e);
        return CommonResult.create(null, CommonResult.FAILED, e.getMessage());
    }

    /**
     *
     * @param e servlet相关的异常
     * @return 返回结果
     */
    @ExceptionHandler(ServletException.class)
    public CommonResult handleServletException(ServletException e){
        //参数错误
        log.error(e.getMessage(), e);
        return CommonResult.create(null, CommonResult.FAILED, e.getMessage());
    }

    /**
     * 通用异常拦截
     * @param e 所有异常
     * @return 返回结果
     */
    @ExceptionHandler(Exception.class)
    public CommonResult handleException(Exception e){

        log.error(e.getMessage(), e);
        return CommonResult.create(null, CommonResult.ERROR, "不好意思, 服务开小差了, 即刻为你修复");
    }

}
